package com.prs.crm.interceptor;

import java.lang.reflect.Method;
import java.util.Collection;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.prs.crm.annotation.FlowActive;
import com.prs.crm.annotation.FlowStart;
import com.prs.crm.annotation.SimpleFlowStart;
import com.prs.crm.context.BeanFactory;
import com.prs.crm.domain.FlowEntity;
import com.prs.crm.domain.SimpleFlowEntity;
import com.prs.crm.domain.flow.WorkFlowInstance;
import com.prs.crm.domain.sys.Form;
import com.prs.crm.service.FlowService;
import com.prs.crm.service.SimpleFlowService;
import com.prs.crm.service.flow.WorkFlowInstanceService;
import com.prs.crm.service.sys.FormService;

public class WorkFlowInterceptor implements Interceptor {

	private static final long serialVersionUID = 1L;

	private static final Logger log = Logger
			.getLogger(WorkFlowInterceptor.class);

	private static final String FORMKEY = "currentForm";

	private static final String VALUEKEY = "activeflowinstances";

	private static final String ENFORCEVALUEKEY = "enforceflowinstance";

	private FormService formService;

	private WorkFlowInstanceService flowInstanceService;

	public void destroy() {
	}

	public void init() {
	}

	private FormService getFormService() {
		try {
			if (formService == null) {
				formService = (FormService) BeanFactory.getBean("formService");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return formService;
	}

	private WorkFlowInstanceService getFlowInstanceService() {
		try {
			if (flowInstanceService == null) {
				flowInstanceService = (WorkFlowInstanceService) BeanFactory
						.getBean("workflowInstanceService");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return flowInstanceService;
	}

	protected Form getForm(Class<? extends FlowEntity> cls) {
		return this.getFormService().getForm(cls.getName());
	}

	public String intercept(ActionInvocation invocation) throws Exception {

		String result = invocation.invoke();
		try {
			if (invocation.getInvocationContext().getValueStack().findValue(
					"originResult") != null
					&& invocation.getInvocationContext().getValueStack()
							.findValue("originResult").equals(
									ActionSupport.SUCCESS)) {
				result = ActionSupport.SUCCESS;
			}
			if (result.equals(ActionSupport.SUCCESS)) {
				Method method = invocation.getAction().getClass().getMethod(
						invocation.getProxy().getMethod(), null);
				activeFlow(invocation, method);
				submitFlow(invocation, method);
				submitSimpleFlow(invocation, method);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	@SuppressWarnings("unchecked")
	private void activeFlow(ActionInvocation invocation, Method method) {
		try {
			invocation.getInvocationContext().getValueStack().set(VALUEKEY,
					null);
			if (method != null) {
				FlowActive annotation = (FlowActive) method
						.getAnnotation(FlowActive.class);
				if (annotation != null) {
					FlowEntity entity = (FlowEntity) PropertyUtils.getProperty(
							invocation.getAction(), annotation.target());
					FlowService service = (FlowService) PropertyUtils
							.getProperty(invocation.getAction(), annotation
									.flowservice());

					if (service.valideSubmit(entity)
							&& (entity == null || !entity.getLocked())) {
						Class<? extends FlowEntity> cls = PropertyUtils
								.getPropertyType(invocation.getAction(),
										annotation.target());
						Form form = this.getForm(cls);
						if (form != null) {
							invocation.getInvocationContext().getValueStack()
									.set(FORMKEY, form);
							if (form.getEnforcement() != null
									&& form.getEnforcement().booleanValue())
								invocation.getInvocationContext()
										.getValueStack().set(ENFORCEVALUEKEY,
												form.getEnforcement());

							// Collection<WorkFlowInstance> instances =
							// this.getFlowInstanceService().findFormInstance(form,null);
							// invocation.getInvocationContext().getValueStack().set(VALUEKEY,instances);

						}

					}

				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	private void submitSimpleFlow(ActionInvocation invocation, Method method) {
		try {
			if (method != null) {
				SimpleFlowStart annotation = (SimpleFlowStart) method
						.getAnnotation(SimpleFlowStart.class);
				if (annotation != null) {
					SimpleFlowService service = (SimpleFlowService) PropertyUtils
							.getProperty(invocation.getAction(), annotation
									.flowservice());
					SimpleFlowEntity entity = (SimpleFlowEntity) PropertyUtils
							.getProperty(invocation.getAction(), annotation
									.target());
					if (entity != null) {
						service.startFlow(entity);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	private void submitFlow(ActionInvocation invocation, Method method) {
		try {
			if (method != null) {
				FlowStart annotation = (FlowStart) method
						.getAnnotation(FlowStart.class);
				if (annotation != null) {
					FlowService service = (FlowService) PropertyUtils
							.getProperty(invocation.getAction(), annotation
									.flowservice());
					FlowEntity entity = (FlowEntity) PropertyUtils.getProperty(
							invocation.getAction(), annotation.target());
					WorkFlowInstance flowInstance = (WorkFlowInstance) PropertyUtils
							.getProperty(invocation.getAction(), "flowInstance");

					if (entity != null && flowInstance != null
							&& !entity.getLocked()) {
						service.submitFlow(entity, flowInstance);
					} else {
						if (invocation.getAction() instanceof ActionSupport) {
							ActionSupport action = (ActionSupport) invocation
									.getAction();
							if (action.getActionErrors().size() < 1) {
								invocation.getInvocationContext()
										.getValueStack().set("prompt",
												"提交失败,未达到提交条件");
							}
						}

					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
		}
	}
}
